﻿using Levfier.GUI.EditorControls.Chains;
using Levfier.Proccessors.Parameters;
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace Levfier.GUI.EditorControls.Parameters
{
    /// <summary>
    /// パラメータのGUIパーツ
    /// </summary>
    [Serializable]
    abstract public class ParameterControl : EditorControl, IParameterControl
    {
        #region 定数

        /// <summary>
        /// 選択時の枠色
        /// </summary>
        protected readonly Brush selectedBrush = new SolidColorBrush(Color.FromArgb(0xFF, 0x00, 0xAA, 0xDE));

        #endregion

        #region プロパティ

        /// <summary>
        /// 変更対象のパラメータ
        /// </summary>
        public ProccessParameter TargetParameter { get; set; }

        /// <summary>
        /// 設定できる値の最大値
        /// </summary>
        public virtual double MaxValue { get; set; }

        /// <summary>
        /// 設定できる値の最小値
        /// </summary>
        public virtual double MinValue { get; set; }

        /// <summary>
        /// プロセッサと接続するためのチェイン
        /// </summary>
        protected IDrawable chainControl;

        /// <summary>
        /// パラメータテーブル
        /// </summary>
        protected IDictionary<string, ProccessParameter> parameters;

        private UserControl propertyControl;

        #endregion

        /// <summary>
        /// 座標を更新する
        /// </summary>
        public override void Update()
        {
            base.Update();

            if (null != this.chainControl)
            {
                //上流・下流の接続先を描画更新する
                this.chainControl.Update();
            }
        }

        /// <summary>
        /// パラメータチェインを設定する
        /// </summary>
        /// <param name="chainControl">描画更新インターフェース</param>
        public void SetParameterChainControl(IDrawable chainControl)
        {
            this.chainControl = chainControl;
        }

        /// <summary>
        /// パラメータチェインを設定する
        /// </summary>
        /// <param name="chainControl">描画更新インターフェース</param>
        public void RemoveParameterChainControl(IDrawable chainControl)
        {
            if (null != this.TargetParameter)
            {
                this.TargetParameter.IsUsed = false;
                this.TargetParameter = null;
            }
            this.parameters = null;
            this.chainControl = null;
        }

        /// <summary>
        /// パラメータを設定する
        /// </summary>
        /// <param name="parameters">パラメータ</param>
        public void SetParameters(IDictionary<string, ProccessParameter> parameters)
        {
            this.parameters = parameters;
            //this.TargetParameter = parameters["Gain"];
            //this.MaxValue = this.TargetParameter.MaxValue;
            //this.MinValue = this.TargetParameter.MinValue;
        }

        /// <summary>
        /// 入力値をデシベル値に変換する
        /// </summary>
        /// <param name="value">入力値</param>
        /// <returns>デシベル値</returns>
        public double ConvertValueToDB(double value)
        {
            return 10 * Math.Log(value, 10.0d);
        }

        /// <summary>
        /// デシベル値を変換する
        /// </summary>
        /// <param name="db">デシベル値</param>
        /// <returns>通常の値</returns>
        public double ConvertDBToValue(double db)
        {
            return Math.Pow(10.0, db / 10.0d);
        }

        /// <summary>
        /// 選択された時の動作
        /// 末端の子クラスで実装すること
        /// </summary>
        /// <param name="sender">イベント発生源</param>
        abstract public override void Select(object sender);

        /// <summary>
        /// 選択解除された時の動作
        /// 末端の子クラスで実装すること
        /// </summary>
        /// <param name="sender">イベント発生源</param>
        abstract public override void Unselect(object sender);

        /// <summary>
        /// パラメータコントロールのプロパティを設定する画面を取得する
        /// </summary>
        /// <returns>パラメータコントロールのプロパティを設定する画面</returns>
        public override System.Windows.Controls.UserControl GetPropertyEditorView()
        {
            if (null != this.parameters)
            {
                if (null == this.propertyControl)
                {
                    this.propertyControl = new ParameterPropertyEditorView(this, this.parameters, this.TargetParameter);
                }
                return this.propertyControl;
            }
            return null;
        }

        /// <summary>
        /// 自分自身を削除する
        /// </summary>
        public override IEnumerable<UIElement> Delete()
        {
            IList<UIElement> deleteTargets = new List<UIElement>();
            ParameterChainControl chain = this.chainControl as ParameterChainControl;

            //内部でthis.RemoveParameterChainControlが呼び出される
            if (null != chain)
            {
                chain.Delete();
                deleteTargets.Add(chain);
            }
            deleteTargets.Add(this);
            return deleteTargets;
        }
    }
}
